Skip to content

fix(compose): retain mounted secret file authority - #281

Draft
seonghobae wants to merge 8 commits into
fix/recovery-evidence-weakref-coverage-b84f0c9from
fix/compose-secret-file-authority-b84f0c9
Draft

fix(compose): retain mounted secret file authority#281
seonghobae wants to merge 8 commits into
fix/recovery-evidence-weakref-coverage-b84f0c9from
fix/compose-secret-file-authority-b84f0c9

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

ACTIVE Draft — retained mounted-secret descriptor authority

Protected main@b84f0c94154043a3473939c01bb6471de5a129ae remains unchanged. This source lane is fix/compose-secret-file-authority-b84f0c9, an explicit child of dependency-root #233@5951b7a4d779903b8924abaef2a387cae50b7f54. Exact current head is c00111e54f21c4cf90036ee66072d5fafaed3ef6, Draft and mechanically mergeable. No source or documentation was written directly to protected main.

Defects proven test-first

Final-component substitution

The earlier standalone Compose bootstrap opened an explicit mounted password-file path through ordinary pathname resolution. A final symlink could therefore redirect password authority away from the mounted-secret object selected by the operator.

The branch retains one package-owned descriptor opened with O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK, rejects platforms that cannot provide the no-follow boundary instead of silently downgrading, proves a regular-file inode before reading, bounds the read, and closes retained authority explicitly. FIFO/non-regular objects, descriptor metadata failures, and close failures remain fixed/content-free failures.

In-place mutation after initial inspection

Test-first commit e0ec0b08bf9ebffbbf5310d86e549a47a0fd1f36 adds a deterministic regression that changes the same retained secret object after the initial descriptor stat and requires fail-closed ConfigError rather than accepting modified bytes.

Current GREEN c00111e54f21c4cf90036ee66072d5fafaed3ef6 snapshots retained regular-file metadata before the bounded read and re-reads descriptor metadata afterward. It rejects observed mode, size, link-count, owner/group, device/inode, mtime, or ctime change through the existing fixed unavailable category. Both observations and the read use the same retained descriptor, so pathname substitution cannot regain authority; mutation after the final metadata observation cannot change the already captured password bytes.

The repair intentionally does not add host-owner/mode assumptions that would reject ordinary container secret mounts, claim immutability against host-root compromise, or expose secret text in argv/logs/telemetry/errors.

Exact current-head validation

The previous body’s queued/pending description is stale. Fresh commit-scoped inventory for unchanged exact c00111e54f21c4cf90036ee66072d5fafaed3ef6 now shows:

  • CI 32372722989: success;
  • Release Acceptance 32372723081: success;
  • Security Scan: absent on this exact head; and
  • SAST Semgrep: absent on this exact head.

Fresh formal reviews and inline review threads are empty. Exact-head CI/release success does not transfer predecessor security evidence; absent Security/SAST and absent approval remain non-passing.

Writer / integration boundary

Fresh lifecycle adjudication in #316 proves retained agent/compose-loopback-publishing@4debfc68655e300a6c393b0cbd3c251daf4faf03 is SUPERSEDED_RETAINED, not current Compose implementation/writer authority: its owning Draft #91 is closed unmerged and explicitly superseded by merged #138, whose merge commit b7f8a48d4745ebd1b429027168c3d2f776c6a4a7 is independently proven in current protected-main ancestry. Preserve that historical ref for provenance; do not delete, rewrite, or transfer its old evidence. fix/compose-bootstrap-runpy-warning-b84f0c9 remains a separate warning-test slice. This correction does not declare the mounted-secret source/test surface globally writer-free: before any future source mutation, freshly inventory all then-current PR/no-PR refs and exact changed paths, and freeze this lane if another actor moves or overlaps it.

Keep #281 Draft behind #233. After #233 reaches protected main through then-live governance, reconcile/retarget this branch to the resulting exact protected base and reacquire one unchanged exact-final-head proof for supported Python including 3.14, exact 100% owned production statement/branch coverage, public docstrings, package/container, Security Scan, SAST, SBOM/provenance/release acceptance, zero valid findings/threads, and any qualifying independent current-last-push approval required by live policy. Do not copy or bypass read-only central .github control-plane logic.

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

Exact current head e6cdad40273fa48f1075d2b443d3904ffbe31c7a closes final-symlink and non-regular/FIFO authority, but one fail-closed normalization gap remains in the new open boundary. os.open(password_file, secure_flags) raises ValueError rather than OSError for an embedded-NUL path; current source catches only OSError, so _load_database_password(Path("private-secret\x00suffix")) leaks a raw implementation exception instead of the fixed content-free ConfigError(_SECRET_UNAVAILABLE) boundary. This is independently reproducible on the supported Python runtime. Please add a focused RED for an embedded-NUL Path and include ValueError in the narrow open-failure normalization without broadening the catch around process-control paths. The branch moved during this invocation, so I am not mutating the source lane.

@seonghobae
seonghobae changed the base branch from main to fix/recovery-evidence-weakref-coverage-b84f0c9 August 20, 2026 06:56
@opencode-agent opencode-agent Bot added area: auth Authentication, authorization, identity, or tenant isolation area: security Security boundary, hardening, or vulnerability prevention priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth Authentication, authorization, identity, or tenant isolation area: security Security boundary, hardening, or vulnerability prevention priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant